package com.imooc.bilibili.service;

import com.imooc.bilibili.dao.UserFollowingDao;
import com.imooc.bilibili.domain.FollowingGroup;
import com.imooc.bilibili.domain.User;
import com.imooc.bilibili.domain.UserFollowing;
import com.imooc.bilibili.domain.UserInfo;
import com.imooc.bilibili.constant.UserConstant;
import com.imooc.bilibili.exception.ConditionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

@Service
public class UserFollowingService {

    @Autowired
    private UserFollowingDao userFollowingDao;

    @Autowired
    private FollowingGroupService followingGroupService;

    @Autowired
    private UserService userService;

    /**
     * 添加用户关注(更新)
     * 这个方法包含新增用户关注和更新用户关注两个逻辑业务，所以是采用先删除再新增的方式
     * 因为需要确保原子性，所以需要加上@Transactional，进行事务处理
     *
     * @param userFollowing
     */
    @Transactional
    public void addUserFollowings(UserFollowing userFollowing) {
        // 获取用户关注的分组id
        Long groupId = userFollowing.getGroupId();
        if (groupId == null) {
            FollowingGroup followingGroup = followingGroupService.getByType(UserConstant.USER_FOLLOWING_GROUP_TYPE_DEFAULT);
            // 给我们要关注的用户，添加到默认分组
            userFollowing.setGroupId(followingGroup.getId());
        } else { // 用户选择了某一个具体的分组
            // 通过分组id查询关注分组表
            FollowingGroup followingGroup = followingGroupService.getById(groupId);
            if (followingGroup == null) {
                throw new ConditionException("关注分组不存在！");
            }
        }
        // 获取关注的用户id
        Long followingId = userFollowing.getFollowingId();
        User user = userService.getUserById(followingId);
        if (user == null) {
            throw new ConditionException("关注的用户不存在！");
        }
        // 这个方法可以包含添加用户关注和更新用户关注，所以这里采用先删除再添加的方式，一举两得
        // 第一个参数是当前用户的id，第二个参数是被关注的用户id
        userFollowingDao.deleteUserFollowing(userFollowing.getUserId(), followingId);
        userFollowing.setCreateTime(new Date());
        userFollowingDao.addUserFollowing(userFollowing);
    }

    /**
     * 获取当前用户的关注列表
     * <p>
     * 第一步：获取关注的用户列表
     * 第二步：根据关注用户的id查询关注用户的基本信息
     * 第三步：将关注用户按关注分组进行分类
     *
     * @param userId
     * @return
     */
    public List<FollowingGroup> getUserFollowings(Long userId) {
        List<UserFollowing> list = userFollowingDao.getUserFollowings(userId);
        //Set<Long> followingIdSet = list.stream().map(UserFollowing::getFollowingId).collect(Collectors.toSet());
        Set<Long> followingIdSet = new HashSet<>();
        for (UserFollowing userFollowing : list) {
            // 添加所有的关注用户的id到集合中
            followingIdSet.add(userFollowing.getFollowingId());
        }
        List<UserInfo> userInfoList = new ArrayList<>();
        if (followingIdSet.size() > 0) {
            // 根据关注用户的id，批量查询用户信息
            userInfoList = userService.getUserInfoByUserIds(followingIdSet);
        }
        for (UserFollowing userFollowing : list) {
            for (UserInfo userInfo : userInfoList) {
                // 如果（要关注的用户id == 用户信息的用户id）
                if (userFollowing.getFollowingId().equals(userInfo.getUserId())) {
                    userFollowing.setUserInfo(userInfo);
                }
            }
        }
        // --------------- 分组逻辑代码 ---------------------
        // 根据用户id，把该用户相关的所有关注分组查询出来
        List<FollowingGroup> groupList = followingGroupService.getByUserId(userId);
        // 1.全部的关注分组
        FollowingGroup allGroup = new FollowingGroup();
        allGroup.setName(UserConstant.USER_FOLLOWING_GROUP_ALL_NAME);
        allGroup.setFollowingUserInfoList(userInfoList);
        List<FollowingGroup> result = new ArrayList<>();
        result.add(allGroup);
        // 2.每个关注分组的详细信息
        /**
         * groupList：用户的关注分组列表；group：关注分组列表的每一个分组
         * list：用户的关注列表；userFollowing：关注列表的每一个用户
         * infoList：每个分组的关注用户的信息列表
         */
        for (FollowingGroup group : groupList) {
            List<UserInfo> infoList = new ArrayList<>();
            for (UserFollowing userFollowing : list) {
                /**
                 * 如果用户的关注分组的id == 关注用户的分组id，
                 * 说明关注的用户属于该分组，
                 * 将该用户的信息添加到该分组的用户信息列表中
                 */
                if (group.getId().equals(userFollowing.getGroupId())) {
                    infoList.add(userFollowing.getUserInfo());
                }
            }
            group.setFollowingUserInfoList(infoList);
            // 将每个关注分组的详细信息，整合到全部关注分组里面去
            result.add(group);
        }
        return result;
    }

    /**
     * 获取用户粉丝列表
     * 第一步：获取当前用户的粉丝列表
     * 第二步：根据粉丝的用户id查询基本信息
     * 第三步：查询当前用户是否已经关注该粉丝(互粉)
     *
     * @param userId
     * @return
     */
    public List<UserFollowing> getUserFans(Long userId) {
        // 获取用户的粉丝列表
        List<UserFollowing> fanList = userFollowingDao.getUserFans(userId);
        // 粉丝id集合
        Set<Long> fanIdSet = new HashSet<>();
        for (UserFollowing userFollowing : fanList) {
            // 添加所有粉丝id到集合中
            fanIdSet.add(userFollowing.getUserId());
        }
        // 粉丝信息集合
        List<UserInfo> userInfoList = new ArrayList<>();
        if (fanIdSet.size() > 0) {
            userInfoList = userService.getUserInfoByUserIds(fanIdSet);
        }
        // --------------- 判断粉丝列表里面有没有我们关注过的(互粉) ------------------
        // 查询当前用户的关注列表
        List<UserFollowing> followingList = userFollowingDao.getUserFollowings(userId);
        /**
         * fanList：用户粉丝列表
         * userInfoList：粉丝信息集合
         */
        for (UserFollowing fan : fanList) {
            for (UserInfo userInfo : userInfoList) {
                if (fan.getUserId().equals(userInfo.getUserId())) {
                    // 初始化关注状态
                    userInfo.setFollowed(false);
                    fan.setUserInfo(userInfo);
                }
            }
            /**
             * fanList：用户粉丝列表
             * followingList：用户关注列表
             * 用户关注的用户id == 粉丝的id，说明两者互粉
             */
            for (UserFollowing following : followingList) {
                if (following.getFollowingId().equals(fan.getUserId())) {
                    // 互粉
                    fan.getUserInfo().setFollowed(true);
                }
            }
        }
        return fanList;
    }

    /**
     * 新建用户关注分组
     *
     * @param followingGroup
     * @return
     */
    public Long addUserFollowingGroups(FollowingGroup followingGroup) {
        followingGroup.setCreateTime(new Date());
        // 分组类型设置为用户自定义分组
        followingGroup.setType(UserConstant.USER_FOLLOWING_GROUP_TYPE_USER);
        followingGroupService.addFollowingGroup(followingGroup);
        // 已经设置了自动返回主键，所以这里可以直接获取分组id
        return followingGroup.getId();
    }

    /**
     * 根据用户id获取用户关注分组
     *
     * @param userId
     * @return
     */
    public List<FollowingGroup> getUserFollowingGroups(Long userId) {
        return followingGroupService.getUserFollowingGroups(userId);
    }

    /**
     * @param userInfoList 分页查询后的用户信息列表
     * @param userId       当前登录的用户id
     * @return
     */
    public List<UserInfo> checkFollowingStatus(List<UserInfo> userInfoList, Long userId) {
        // 查询当前登录用户的关注用户列表
        List<UserFollowing> userFollowingList = userFollowingDao.getUserFollowings(userId);
        // 遍历分页查询后的用户信息列表
        for (UserInfo userInfo : userInfoList) {
            // 先初始化关注状态
            userInfo.setFollowed(false);
            // 遍历用户关注列表
            for (UserFollowing userFollowing : userFollowingList) {
                if (userFollowing.getFollowingId().equals(userInfo.getUserId())) {
                    // 当前用户关注过这个用户
                    userInfo.setFollowed(true);
                }
            }
        }
        return userInfoList;
    }
}
